﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace OrganizedConfusion
{
    public class InputManager
    {
        #region Fields
        KeyboardState OldKeyboardState;
        KeyboardState NewKeyboardState;
        GamePadState OldGamePadState;
        GamePadState NewGamePadState;
        GamePadThumbSticks LeftStick, RightStick;
        #endregion

        public InputManager() { }

        #region Methods
        /// <summary>
        /// A method that returns true only if this is the first time the key is pressed.
        /// Buffered input the keyboard.
        /// </summary>
        /// <param name="key">The key the user presses</param>
        /// <returns></returns>
        public bool KeyPressedBuffered(Keys key)
        {
            NewKeyboardState = Keyboard.GetState();

            if (NewKeyboardState.IsKeyDown(key) && !OldKeyboardState.IsKeyDown(key))
            {
                OldKeyboardState = NewKeyboardState;
                return true;
            }

            else if (!NewKeyboardState.IsKeyDown(key) && OldKeyboardState.IsKeyDown(key))
            {
                OldKeyboardState = NewKeyboardState;
                return false;
            }

            return false;
        }

        /// <summary>
        /// A method that returns true only if this is the first time the button is pressed.
        /// Works with thumbsticks.
        /// Buffered input for the controller.
        /// </summary>
        /// <param name="button">The button the user presses</param>
        /// <returns></returns>
        public bool ButtonPressedBuffered(Buttons button)
        {
            NewGamePadState = GamePad.GetState(PlayerIndex.One);

            if (NewGamePadState.IsButtonDown(button) && !OldGamePadState.IsButtonDown(button))
            {
                OldGamePadState = NewGamePadState;
                return true;
            }
            else if (!NewGamePadState.IsButtonDown(button) && OldGamePadState.IsButtonDown(button))
            {
                OldGamePadState = NewGamePadState;
                return false;
            }

            return false;
        }

        /// <summary>
        /// Returns immediate input for the key that is pressed.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool KeyHeldDown(Keys key)
        {
            return Keyboard.GetState().IsKeyDown(key);
        }

        /// <summary>
        /// Returns immediate input for the button pressed.
        /// Works with thumbsticks also.
        /// </summary>
        /// <param name="button"></param>
        /// <returns></returns>
        public bool ButtonHeldDown(Buttons button)
        {
            return GamePad.GetState(PlayerIndex.One).IsButtonDown(button);
        }

        /// <summary>
        /// Sets the current state of the keyboard.
        /// </summary>
        /// <param name="State"></param>
        public void AcquireKeyboard(KeyboardState State)
        {
            OldKeyboardState = State;
        }

        /// <summary>
        /// Sets the current state of the controller.
        /// </summary>
        /// <param name="State"></param>
        public void AcquireGamePad(GamePadState State)
        {
            OldGamePadState = State;
        }

        /// <summary>
        /// Returns a vector of the Left Thumbstick Orientation
        /// Left & Down are Negative. Up & Right are Positive.\n
        /// Range is -1 to 1.
        /// </summary>
        /// <param name="Player"></param>
        /// <returns></returns>
        public Vector2 LeftStickPressure(PlayerIndex Player)
        {
            return GamePad.GetState(Player).ThumbSticks.Left;
        }

        /// <summary>
        /// Returns a vector of the Right Thumbstick Orientation.
        /// Left & Down are Negative. Up & Right are Positive.
        /// Range is -1 to 1.
        /// </summary>
        /// <param name="Player"></param>
        /// <returns></returns>
        public Vector2 RightStickPressure(PlayerIndex Player)
        {
            return GamePad.GetState(Player).ThumbSticks.Right;
        }

        public bool LeftStickY_Buffered(PlayerIndex Player)
        {
            GamePadThumbSticks NewState = GamePad.GetState(Player).ThumbSticks;

            if (NewState.Left.Y > 0.15f || NewState.Left.Y < -0.15f)
            {
                LeftStick = NewState;
                return true;
            }
            else if (NewState.Left.Y < 0.15f && NewState.Left.Y > -0.15f)
            {
                LeftStick = NewState;
                return false;
            }

            return false;
        }

        public bool LeftStickY_Buffered(PlayerIndex Player, int Direction)
        {
            GamePadThumbSticks NewState = GamePad.GetState(Player).ThumbSticks;

            if (Direction < 0) // Checking down
            {
                if (NewState.Left.Y < -0.15f)
                {
                    LeftStick = NewState;
                    return true;
                }
                else if (NewState.Left.Y < 0.15f && NewState.Left.Y > -0.15f)
                {
                    LeftStick = NewState;
                    return false;
                }
            }
            else
            {
                if (NewState.Left.Y > 0.15f && LeftStick.Left.Y != NewState.Left.Y)
                {
                    LeftStick = NewState;
                    return true;
                }
                else if (NewState.Left.Y < 0.15f && NewState.Left.Y > -0.15f)
                {
                    LeftStick = NewState;
                    return false;
                }
            }

            return false;
        }

        public bool LeftStickXY_Buffered(PlayerIndex Player)
        {
            GamePadThumbSticks NewState = GamePad.GetState(Player).ThumbSticks;

            if (NewState.Left.X > 0.15f || NewState.Left.X < -0.15f)
            {
                if (NewState.Left.Y > 0.15f || NewState.Left.Y < -0.15f)
                {
                    LeftStick = NewState;
                    return true;
                }
            }
            else if (NewState.Left.X < 0.15f && NewState.Left.X > -0.15f)
            {
                if (NewState.Left.Y < 0.15f && NewState.Left.Y > -0.15f)
                {
                    LeftStick = NewState;
                    return false;
                }
            }

            return false;
        }

        public bool LeftStickX_Buffered(PlayerIndex Player)
        {
            GamePadThumbSticks NewState = GamePad.GetState(Player).ThumbSticks;

            if (NewState.Left.X > 0.15f || NewState.Left.X < -0.15f)
            {
                LeftStick = NewState;
                return true;
            }
            else if (NewState.Left.X < 0.15f && NewState.Left.X > -0.15f)
            {
                LeftStick = NewState;
                return false;
            }

            return false;
        }

        public bool RightStickBuffered(PlayerIndex Player)
        {
            GamePadThumbSticks NewState = GamePad.GetState(Player).ThumbSticks;

            if (NewState.Right.X > 0.15f || NewState.Right.X < -0.15f)
            {
                if (NewState.Right.Y > 0.15f || NewState.Right.Y < -0.15f)
                {
                    RightStick = NewState;
                    return true;
                }
            }
            else if (NewState.Right.X < 0.15f && NewState.Right.X > -0.15f)
            {
                if (NewState.Right.Y < 0.15f && NewState.Right.Y > -0.15f)
                {
                    RightStick = NewState;
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Returns the float value of how much the left trigger is being pressed.
        /// Range is 0 to 1.
        /// </summary>
        /// <param name="Player"></param>
        /// <returns></returns>
        public float LeftTriggerPressure(PlayerIndex Player)
        {
            return GamePad.GetState(Player).Triggers.Left;
        }

        /// <summary>
        /// Returns the float value of how much the right trigger is being pressed.
        /// Range is 0 to 1.
        /// </summary>
        /// <param name="Player"></param>
        /// <returns></returns>
        public float RightTriggerPressure(PlayerIndex Player)
        {
            return GamePad.GetState(Player).Triggers.Right;
        }

        #endregion
    }
}
